package com.guaoran.study.future;

import com.guaoran.study.map.struct.one.Person;
import com.guaoran.study.map.struct.one.User;

import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @Desc： CompletableFuture 学习
 * @Auth gucheng
 * @Date 2020/10/29 上午9:47.
 */
public class CompletableFutureDemo {

    public static void main2(String[] args) {
//        CompletableFuture.runAsync();
//        CompletableFuture.supplyAsync();
        CompletableFuture future = new CompletableFuture();
//        future.thenAcceptAsync().thenApply().thenApplyAsync();

        Person person = new Person();
        person.setId(1L);
        person.setEmail("guchengniuniu@163.com");
        person.setName("guaoran");

//        future.thenApply(person2User(person));

    }
    public static User person2User(Person person){
        User user = new User();
        user.setAge(18);
        return user;
    }


    public static void main(String[] args) {
        thenCombine();
        thenApply();
        applyToEither();
    }

    /**
     * 描述串行关系，主要是 thenApply、thenAccept、thenRun 和 thenCompose 这
     */
    public static void thenApply(){
        CompletableFuture<String> f0 =
                CompletableFuture.supplyAsync(
                        () -> "Hello World")      //①
                        .thenApply(s -> s + " QQ")  //②
                        .thenApply(String::toUpperCase);//③

        System.out.println(f0.join());
    }

    /**
     * 描述 AND 汇聚关系，主要是 thenCombine、thenAcceptBoth 和 runAfterBoth 系列的接口
     */
    public static void thenCombine(){
        //任务1：洗水壶->烧开水
        CompletableFuture<Void> f1 =
                CompletableFuture.runAsync(()->{
                    System.out.println("T1:洗水壶...");
                    sleep(1, TimeUnit.SECONDS);

                    System.out.println("T1:烧开水...");
                    sleep(15, TimeUnit.SECONDS);
                });
        //任务2：洗茶壶->洗茶杯->拿茶叶
        CompletableFuture<String> f2 =
                CompletableFuture.supplyAsync(()->{
                    System.out.println("T2:洗茶壶...");
                    sleep(1, TimeUnit.SECONDS);

                    System.out.println("T2:洗茶杯...");
                    sleep(2, TimeUnit.SECONDS);

                    System.out.println("T2:拿茶叶...");
                    sleep(1, TimeUnit.SECONDS);
                    return "龙井";
                });
        //任务3：任务1和任务2完成后执行：泡茶
        CompletableFuture<String> f3 =
                f1.thenCombine(f2, (__, tf)->{
                    System.out.println("T1:拿到茶叶:" + tf);
                    System.out.println("T1:泡茶...");
                    return "上茶:" + tf;
                });
        //等待任务3执行结果
        System.out.println(f3.join());
    }

    /**
     * 描述 OR 汇聚关系，主要是 applyToEither、acceptEither 和 runAfterEither 系列的接口
     */
    public static void applyToEither(){

        CompletableFuture<String> f1 =
                CompletableFuture.supplyAsync(()->{
                    int t = getRandom(10);
                    sleep(t, TimeUnit.SECONDS);
                    return String.valueOf(t);
                });

        CompletableFuture<String> f2 =
                CompletableFuture.supplyAsync(()->{
                    int t = getRandom(10);
                    sleep(t, TimeUnit.SECONDS);
                    return String.valueOf(t);
                });

        CompletableFuture<String> f3 =
                f1.applyToEither(f2,s -> s);

        System.out.println(f3.join());
    }

    public static void exceptionally(){

        CompletableFuture<Integer> f0 =
                CompletableFuture
                .supplyAsync(()->7/0)
                .thenApply(r->r*10)
                .exceptionally(e->0);
        System.out.println(f0.join());
    }



    static int getRandom(int i) {

        return new Random().nextInt(i);
    }

    static void sleep(int t, TimeUnit u) {
        try {
            u.sleep(t);
        }catch(InterruptedException e){}
    }


}
